package io.red;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 *
 * @author Mariano Zapata
 */
public class GestorInterfacesRed {
    
    private NetworkInterface interfaz;
    private InetAddress inet;
    private int tipoIP;
    
    public static final int IPV4= 0;
    public static final int IPV6= 1;
    
    public GestorInterfacesRed() {
        interfaz= null;
        inet= null;
        tipoIP= -1;
    }
    
    /**
     * @param nombreInterfazConfigurada debe ser el display name de la interfaz de red.
     * @param tipoIPConfigurada indica el tipo de IP seleccionada (IPv4 o IPv6).
     * @throws SocketException si no se encuentra una interfaz de red con el nombre especificado o si la
     * dirección IP a utilizar no es la correcta.
     */
    public void configurar(String nombreInterfazConfigurada, int tipoIPConfigurada) throws SocketException
    {
        tipoIP= tipoIPConfigurada;
        Enumeration<NetworkInterface> nets= NetworkInterface.getNetworkInterfaces();
        while (nets.hasMoreElements())
        {
            NetworkInterface actual= nets.nextElement();
            if (actual.getDisplayName().equals(nombreInterfazConfigurada))
            {
                interfaz= actual;
                this.configurarInetAddress(actual, tipoIP);
                break;
            }
        }
        if (interfaz == null)
            throw new SocketException("No se encuentra la tarjeta de red especificada en la configuración.");
    }
    
    private void configurarInetAddress(NetworkInterface ni, int tipoIP) throws SocketException
    {
        Enumeration<InetAddress> direcciones= ni.getInetAddresses();
        while (direcciones.hasMoreElements())
        {
            InetAddress ia= direcciones.nextElement();
            String ip= ia.getHostAddress();
            switch (tipoIP)
            {
                case IPV4:
                    if (this.esIPv4(ip))
                        inet= ia;
                    break;
                case IPV6:
                    if (!this.esIPv4(ip))
                        inet= ia;
                    break;
            }
            if (inet != null)
                break;
        }
        if (inet == null)
            throw new SocketException("No coincide el tipo de dirección IP configurado con el de la tarjeta de red.");
    }
    
    private boolean esIPv4(String ip) {
        return (ip.length() <= 15);
    }
    
    public List<String> getInterfacesRed() throws SocketException
    {
        ArrayList<String> interfaces= new ArrayList<String>();
        Enumeration<NetworkInterface> nets= NetworkInterface.getNetworkInterfaces();
        while (nets.hasMoreElements())
            interfaces.add(nets.nextElement().getDisplayName());
        return interfaces;
    }
    
    public InetAddress getInetAddress() {
        return inet;
    }
    
    public String getDireccionIP() throws UnknownHostException
    {
        if (interfaz == null)
            return "0.0.0.0";
        else
            return inet.getHostAddress();
    }
    
    public String getNombre()
    {
        if (interfaz == null)
            return "No se ha configurado una interfaz de red.";
        else
            return interfaz.getDisplayName();
    }
    
    public int getTipoIP() {
        return tipoIP;
    }
}
